package utp.tepc.jogogeneral;

import java.util.*;

public class General implements IGeneral
{
    public static final String NOME_JOGO = "GENERAL";
    public static final Integer SEQUENCIA = 25;
    public static final Integer FULA = 30;
    public static final Integer QUADRA = 40;
    public static final Integer GENERAL = 50;
    // public static final Integer REGULAR = 5;
    public static final int MAX_LANCES = 3;
    public static final int MAX_RODADAS = 10;
	
    private List<Dado> dados;
    private Jogo jogoControl;

    public General(Jogo j)
    {
	this.jogoControl = j;
	this.dados = new ArrayList<Dado>();

	for (int i = 0; i < 5; i++)
	    dados.add(new Dado());
    }

    public Jogo getJogo()
    {
	return this.jogoControl;
    }

    private boolean isGeneral() throws Exception
    {
	int aux = dados.get(0).getNumeroSorteado();

	for (Dado d : dados)
	    if (d.getNumeroSorteado() != aux)
		return false;

	return true;
    }

    @SuppressWarnings(
    { "rawtypes", "unchecked" })
    private boolean isFula() throws Exception
    {
	Hashtable aux = new Hashtable();
	Hashtable result = new Hashtable();

	for (Dado d : dados)
	{
	    if (aux.containsKey(d.getNumeroSorteado()))
	    {
		Integer value = (Integer) aux.get(d.getNumeroSorteado());
		aux.put(d.getNumeroSorteado(), ++value);
	    }
	    else
	    {
		aux.put(d.getNumeroSorteado(), new Integer(1));
	    }
	}

	if (aux.size() != 2)
	    return false;

	for (Dado d : dados)
	{
	    if (aux.containsKey(d.getNumeroSorteado()))
	    {
		result.put("valor-1", aux.get(d.getNumeroSorteado()));
		aux.remove(d.getNumeroSorteado());
		break;
	    }
	}

	for (Dado d : dados)
	{
	    if (aux.containsKey(d.getNumeroSorteado()))
	    {
		result.put("valor-2", aux.get(d.getNumeroSorteado()));
		break;
	    }
	}

	if (result.size() > 0)
	    if (((Integer) result.get("valor-1") == 2 || (Integer) result.get("valor-1") == 3)
		    && ((Integer) result.get("valor-2") == 2 || (Integer) result.get("valor-2") == 3))
		return true;

	return false;
    }

    @SuppressWarnings(
    { "rawtypes", "unchecked" })
    private boolean isQuadra() throws Exception
    {
	Hashtable aux = new Hashtable();

	for (Dado d : dados)
	{
	    if (aux.containsKey(d.getNumeroSorteado()))
	    {
		Integer value = (Integer) aux.get(d.getNumeroSorteado());
		aux.put(d.getNumeroSorteado(), ++value);
	    }
	    else
	    {
		aux.put(d.getNumeroSorteado(), new Integer(1));
	    }
	}

	for (Dado d : dados)
	{
	    if (aux.containsKey(d.getNumeroSorteado()) && (Integer) aux.get(d.getNumeroSorteado()) == 4)
		return true;
	}

	return false;
    }

    private boolean isSequencia() throws Exception
    {
	int result[] = new int[dados.size()];

	for (int i = 0; i < dados.size(); i++)
	    result[i] = dados.get(i).getNumeroSorteado().intValue();

	Arrays.sort(result);

	for (int i = 0; i < result.length - 1; i++)
	    if (result[i] != result[i + 1] - 1)
		return false;

	return true;
    }

    @Override
    public List<Dado> getDados()
    {
	return dados;
    }

    @Override
    public int[] validaJogada() throws Exception
    {
	ArrayList<Integer> jogadas = new ArrayList<Integer>();
	int[] aux;

	if (isSequencia())
	    jogadas.add(SEQUENCIA);

	if (isFula())
	    jogadas.add(FULA);

	if (isQuadra())
	    jogadas.add(QUADRA);

	if (isGeneral())
	    jogadas.add(GENERAL);

	aux = new int[jogadas.size()];

	for (int j = 0; j < aux.length; j++)
	    aux[j] = jogadas.get(j).intValue();

	return aux;
    }

    @Override
    public boolean temNovaRodada(int rodada)
    {
	if (rodada < MAX_RODADAS)
	    return true;

	return false;
    }

    @Override
    public boolean temNovoLancamento(int qtd)
    {
	if (qtd >= MAX_LANCES)
	    return false;

	return true;
    }

    @Override
    public String getNomeJogada(int tipos)
    {
	if (tipos == SEQUENCIA)
	    return "Sequencia";

	if (tipos == FULA)
	    return "Fula";

	if (tipos == QUADRA)
	    return "Quadra";

	if (tipos == GENERAL)
	    return "General";
	
	if(tipos > 0)
	    return Integer.toString(tipos);

	return null;
    }

    @Override
    public boolean podeMarcarPonto(HashMap<Integer, Integer> pontuacaoAtual, int pontuacaoNova)
    {
	for(Integer key : pontuacaoAtual.keySet())
	{
	    if(pontuacaoAtual.get(key) == pontuacaoNova)
		return false;
	}	

	return true;
    }

    public int getPontuacao(int tipoPontuacao)
    {
	if (tipoPontuacao == SEQUENCIA)
	    return 25;

	if (tipoPontuacao == FULA)
	    return 30;

	if (tipoPontuacao == QUADRA)
	    return 40;

	if (tipoPontuacao == GENERAL)
	    return 50;

	return tipoPontuacao;
    }
    

    @Override
    public String getJogoNome()
    {
	return NOME_JOGO;
    }
}
